from binn import *

lib.binn_new_iter.restype = ct.c_voidp
def binn_new_iter():
    return lib.binn_new_iter()

lib.binn_free_iter.argtypes = [ct.c_voidp]
def binn_free_iter(binn_iter):
    return lib.binn_free_iter(binn_iter)

lib.binn_iter_init.argtypes = [
    ct.c_voidp, ct.c_voidp, ct.c_int
]
lib.binn_iter_init.restype = ct.c_bool


def binn_iter_init(it, pbuf, typ):
    #if not isinstance(it, ct.c_voidp):
    #    it = ct.c_voidp(it)
    if not isinstance(pbuf, ct.c_voidp):
        pbuf = ct.c_voidp(pbuf)
    return lib.binn_iter_init(it, pbuf, typ)

lib.binn_object_next.restype = ct.c_bool
def binn_object_next(it, key, val):
    #if not isinstance(it, ct.c_voidp):
    #    it = ct.c_voidp(it)
    if not isinstance(val, ct.c_voidp):
        val = ct.c_voidp(val)
    return lib.binn_object_next(it, key, val)

lib.binn_map_next.restype = ct.c_bool
def binn_map_next(it, iden, val):
    #if not isinstance(it, ct.c_voidp):
    #    it = ct.c_voidp(it)
    if not isinstance(val, ct.c_voidp):
        val = ct.c_voidp(val)
    return lib.binn_map_next(it, iden, val)

lib.binn_list_next.restype = ct.c_bool
def binn_list_next(it, val):
    #if not isinstance(it, ct.c_voidp):
    #    it = ct.c_voidp(it)
    if not isinstance(val, ct.c_voidp):
        val = ct.c_voidp(val)
    return lib.binn_list_next(it, val)



lib.binn_get_bool.restype = ct.c_bool
def binn_get_bool(binn):
    val = ct.c_bool(0)
    if not isinstance(binn, ct.c_voidp):
        binn = ct.c_voidp(binn)
    lib.binn_get_bool(binn, ct.byref(val))
    return val.value


lib.binn_get_int32.restype = ct.c_bool
def binn_get_int32(binn):
    val = ct.c_int32(0)
    if not isinstance(binn, ct.c_voidp):
        binn = ct.c_voidp(binn)
    lib.binn_get_int32(binn, ct.byref(val))
    return val.value

lib.binn_get_int64.restype = ct.c_bool
def binn_get_int64(binn):
    val = ct.c_int64(0)
    if not isinstance(binn, ct.c_voidp):
        binn = ct.c_voidp(binn)
    lib.binn_get_int64(binn, ct.byref(val))
    return val.value

lib.binn_get_float.restype = ct.c_bool
def binn_get_float(binn):
    val = ct.c_float(0)
    if not isinstance(binn, ct.c_voidp):
        binn = ct.c_voidp(binn)
    lib.binn_get_float(binn, ct.byref(val))
    return val.value

lib.binn_get_double.restype = ct.c_bool
def binn_get_double(binn):
    val = ct.c_double(0)
    if not isinstance(binn, ct.c_voidp):
        binn = ct.c_voidp(binn)
    lib.binn_get_double(binn, ct.byref(val))
    return val.value

lib.binn_get_str.restype = ct.c_char_p
def binn_get_str(binn):
    if not isinstance(binn, ct.c_voidp):
        binn = ct.c_voidp(binn)
    return lib.binn_get_double(binn)



from datatypes import *


class BinnIter:

    def __init__(self, typ):
        self.typ = typ
        #self.iter = binn_new_iter()
        self.iter = ct.c_buffer(256)
        self.binn  = binn_object()
        self.key = ct.create_string_buffer(b'0' * 256)
        self.iden = ct.c_int(0)
    def __del__(self):
        #binn_free_iter(self.iter) 
        binn_free(self.binn)    
    def next(self):
        ret = False
        if self.typ == BINN_OBJECT:
            ret = binn_object_next(self.iter, self.key, self.binn)
        elif self.typ == BINN_MAP:
            ret = binn_map_next(self.iter, ct.byref(self.iden), self.binn)
        elif self.typ == BINN_LIST:
            ret = binn_list_next(self.iter, self.binn)
        else:
            raise ValueError('')
        return ret
    def get_iden(self):
        return self.iden.value
    def get_key(self):
        return self.key.value.decode()
    def get_type(self):
        return binn_type(self.binn)
    def get_value(self):
        typ = self.get_type()
        if is_int(typ):
            return self.get_int64()
        elif is_floating_point(typ):
            return self.get_double()
        else:
            return self.binn
        #if typ == BINN_BOOL:
        #    return self.get_bool()
        #elif typ == BINN_FLOAT32:
        #    return self.get_float()
        #elif typ == BINN_FLOAT64:
        #    return self.get_double()
        #elif typ == BINN_INT64:
        #    return self.get_int64()
        
    def get_bool(self):
        return binn_get_bool(self.binn)
    def get_int32(self):
        return binn_get_int32(self.binn)
    def get_int64(self):
        return binn_get_int64(self.binn)
    def get_float(self):
        return binn_get_float(self.binn)
    def get_double(self):
        return binn_get_double(self.binn)
    def get_str(self):
        return binn_get_str(self.binn)

